#include "StdAfx.h"
#include "TextureManager.h"
#include "Texture.h"
#include "RenderTarget.h"


#if RENDER_SYSTEM == RENDER_SYSTEM_GLES2

	#if PLATFORM == PLATFORM_WIN32


	bool RenderTarget::Create()
	{
		if (!m_hWnd) 
			return false;

        m_eglWindow = m_hWnd;
        // Get the associated device context
        m_hDC = GetDC(m_hWnd);

        if (!m_hDC) 
			return false;
        /*

        Step 1 - Get the default display.

        EGL uses the concept of a "display" which in most environments

        corresponds to a single physical screen. Since we usually want

        to draw to the main screen or only have a single screen to begin

        with, we let EGL pick the default display.

        Querying other displays is platform specific.

        */

       m_eglDisplay = eglGetDisplay(m_hDC);
       if(m_eglDisplay == EGL_NO_DISPLAY)

            m_eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY);



        /*

        Step 2 - Initialize EGL.

        EGL has to be initialized with the display obtained in the

        previous step. We cannot use other EGL functions except

        eglGetDisplay and eglGetError before eglInitialize has been

        called.

        If we're not interested in the EGL version number we can just

        pass NULL for the second and third parameters.

        */

        EGLint iMajorVersion, iMinorVersion;

        if (!eglInitialize(m_eglDisplay, &iMajorVersion, &iMinorVersion))

            return false;



        /*

        Step 3 - Make OpenGL ES the current API.

        EGL provides ways to set up OpenGL ES and OpenVG contexts

        (and possibly other graphics APIs in the future), so we need

        to specify the "current API".

        */

        eglBindAPI(EGL_OPENGL_ES_API);

        //if (!TestEGLError(m_hWnd, "eglBindAPI"))

        //  return false;



        /*

        Step 4 - Specify the required configuration attributes.

        An EGL "configuration" describes the pixel format and type of

        surfaces that can be used for drawing.

        For now we just want to use the default Windows surface,

        i.e. it will be visible on screen. The list

        has to contain key/value pairs, terminated with EGL_NONE.

        */

        const EGLint pi32ConfigAttribs[] =

        {

            EGL_LEVEL,				0,

            EGL_SURFACE_TYPE,		EGL_WINDOW_BIT,

            EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,

            EGL_NATIVE_RENDERABLE,	EGL_FALSE,

            //EGL_DEPTH_SIZE,			EGL_DONT_CARE,

            EGL_ALPHA_SIZE,         8,

            EGL_BLUE_SIZE,          8,

            EGL_GREEN_SIZE,         8,

            EGL_RED_SIZE,           8,

            EGL_DEPTH_SIZE,			16,

            EGL_STENCIL_SIZE,       8,

            EGL_NONE

        };



        /*

        Step 5 - Find a config that matches all requirements.

        eglChooseConfig provides a list of all available configurations

        that meet or exceed the requirements given as the second

        argument. In most cases we just want the first config that meets

        all criteria, so we can limit the number of configs returned to 1.

        */

        EGLint iConfigs;

        if (!eglChooseConfig(m_eglDisplay, pi32ConfigAttribs, &m_eglConfig, 1, &iConfigs) || (iConfigs != 1))

        {

            return false;

        }





        /*

        Step 6 - Create a surface to draw to.

        Use the config picked in the previous step and the native window

        handle when available to create a window surface. A window surface

        is one that will be visible on screen inside the native display (or

        fullscreen if there is no windowing system).

        Pixmaps and pbuffers are surfaces which only exist in off-screen

        memory.

        */

        m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_eglWindow, NULL);



        if(m_eglSurface == EGL_NO_SURFACE)

        {

            eglGetError(); // Clear error

            m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, NULL, NULL);

        }


		/*
        if (!TestEGLError(m_hWnd, "eglCreateWindowSurface"))

        {

            return false;

        }
		*/




        /*

        Step 7 - Create a context.

        EGL has to create a context for OpenGL ES. Our OpenGL ES resources

        like textures will only be valid inside this context

        (or shared contexts)

        */

        EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

        m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, NULL, ai32ContextAttribs);

		/*
        if (!TestEGLError(m_hWnd, "eglCreateContext"))

        {

            return false;

        }
		*/



        /*

        Step 8 - Bind the context to the current thread and use our

        window surface for drawing and reading.

        Contexts are bound to a thread. This means you don't have to

        worry about other threads and processes interfering with your

        OpenGL ES application.

        We need to specify a surface that will be the target of all

        subsequent drawing operations, and one that will be the source

        of read operations. They can be the same surface.

        */

        //eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);

		/*
        if (!TestEGLError(m_hWnd, "eglMakeCurrent"))

        {

            return false;

        }
		*/
            
		/*
        RECT rcClient;
        GetClientRect(m_hWnd, &rcClient);
     
		int h = rcClient.bottom - rcClient.top;

		m_vpLeft = rcClient.left;
		m_vpWidth = rcClient.right - rcClient.left;
		m_vpHeight = rcClient.bottom - rcClient.top;
		m_vpTop = h - rcClient.top - m_vpHeight;
		
		glViewport(m_vpLeft,m_vpTop,m_vpWidth,m_vpHeight);
		*/

		return true;
	}

	void RenderTarget::release()
	{
		
		/* EGL clean up */
		eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		eglDestroySurface(m_eglDisplay, m_eglSurface);
		eglDestroyContext(m_eglDisplay, m_eglContext);
		eglTerminate(m_eglDisplay);


		 /*
         Step 11 - Destroy the eglWindow.

         Again, this is platform specific and delegated to a separate function.

         */

		// Release the device context
		if (m_hDC) ReleaseDC(m_hWnd, m_hDC);

		delete this;
	}

	const ITexture*	RenderTarget::getTexture()
	{
		assert(0);
		return 0;
	}

	void RenderTarget::onAttach()
	{
		TestGLError("befor...");
		eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
		TestGLError("eglMakeCurrent");
		glBindFramebuffer(GL_FRAMEBUFFER,m_FrameBufferObj);
		TestGLError("RenderTarget::onAttach | glBindFramebuffer");
	}

	void RenderTarget::onDetach()
	{
		//eglMakeCurrent(m_eglDisplay,0,0,0);
		//TestGLError("onDetach");
	}

	void RenderTarget::onEndFrame(int layer)
	{
		//PP_BY_NAME_START("onEndFrame");
		eglSwapBuffers(m_eglDisplay, m_eglSurface);
		TestGLError("RenderTarget::onEndFrame | eglSwapBuffers");
		//PP_BY_NAME_STOP();
	}

	bool		RenderTarget::getTextureData(void  *pData)
	{
		assert(0);
		return false;
	}

	void RenderTarget::getRect(Rect *rc)
	{
		RECT rt;
		GetClientRect(m_hWnd,&rt);
		rc->left = rt.left;
		rc->top = rt.top;
		rc->right = rt.right;
		rc->bottom = rt.bottom;
	}

	/*
	void RenderTarget::setShaderProgram(rkt::IShaderProgram* pShader)
	{
		m_RenderState.m_pShaderProgram = pShader;
	}

	rkt::IShaderProgram* RenderTarget::getShaderProgram()
	{
		return m_RenderState.m_pShaderProgram;
	}
	*/

    #elif PLATFORM == PLATFORM_IOS
	//todo...
	#endif

#else

void RenderTarget::release()
{
	delete this;
}

const ITexture*	RenderTarget::getTexture()
{
	return 0;
}

void 		RenderTarget::onAttach()
{
}

void 		RenderTarget::onDetach()
{
}

void 		RenderTarget::onEndFrame(int layer)
{
	PP_BY_NAME_START("glFinish");
	::glFinish();
	PP_BY_NAME_STOP();
	PP_BY_NAME_START("SwapBuffers");
	if(layer == 0)
		wglSwapLayerBuffers(dc,WGL_SWAP_MAIN_PLANE);
	else
		//#define WGL_SWAP_OVERLAY1       0x00000002
		//#define WGL_SWAP_OVERLAY2       0x00000004
		//#define WGL_SWAP_OVERLAY3       0x00000008
		//#define WGL_SWAP_OVERLAY4       0x00000010
		//#define WGL_SWAP_OVERLAY5       0x00000020
		//#define WGL_SWAP_OVERLAY6       0x00000040
		//#define WGL_SWAP_OVERLAY7       0x00000080
		wglSwapLayerBuffers(dc,(1 << layer));

	PP_BY_NAME_STOP();
}

bool		RenderTarget::getTextureData(void  *pData)
{
	return false;
}

void		RenderTarget::getRect(RECT *rc)
{
	GetClientRect(m_hWnd,rc);
}

#endif